JavaScript is partly a functional language.
To learn JavaScript, we got to learn the functional parts of JavaScript.
In this article, we’ll look at how to use currying with JavaScript.
Unary Function
A unary function is a function that takes a single argument.
For example, a unary function is:
const identity = (x) => x;
Binary Function
A binary function is a function that takes 2 arguments.
An example of one is:
const add = (x, y) => x + y;
Variadic Function
A variadic function is a function that takes a variable number of arguments.
We can define a variadic function in JavaScript by using the rest operator:
function variadic(...args) {
console.log(args)
}
args
has an array of all the arguments we pass in.
Currying
Curry is converting a function with multiple arguments into nested unary functions.
This is useful because it lets us create functions with some of the arguments applied.
For example, we can convert a binary function:
const add = (x, y) => x + y;
into a function unary function that returns another unary function by writing:
const addCurried = x => y => x + y;
The addCurried
function takes a parameter x
and returns a function that takes a parameter y
which returns the sum of x
and y
together.
Then we can use it by writing:
const add1 = addCurried(1);
const sum = add1(2);
We called addCurried
with 1 to return a function with x
set to 1 and assign that to the add
variable.
Then we call add1
with 2 to return the final sum.
We can generalize this by creating a function that returns a function that takes one argument, which is the binary function.
Inside that function, we return a function that takes the 2nd argument.
And inside that, we return the result of the binary function called with the parameters of the outer functions.
For example, we can write:
const curry = (binaryFn) => {
return (firstArg) => {
return (secondArg) => {
return binaryFn(firstArg, secondArg);
};
};
};
const add = (x, y) => x + y
const sum = curry(add)(1)(2);
to create the curry
function to do what we described.
Then we can pass in any binary function like our add
function.
And then it’ll be curried automatically.
We can generalize this further with a curry
function that recursively returns functions with one argument, until there’s only one argument left.
For instance, we can write:
let curry = (fn) => {
if (typeof fn !== 'function') {
throw Error('No function provided');
}
return function curriedFn(...args) {
if (args.length < fn.length) {
return function(...moreArgs) {
return curriedFn(...[...args, ...moreArgs]);
};
}
return fn(...args);
};
};
We check if fn
is a function.
If it is, then we return a function that returns a function that calls the same function that’s returned if fn
has more parameters than args
.
If there are more arguments in fn
than args
, that means that we can curry it more.
If the number of parameters of the curried function is the same as the number of parameters in fn
, then we can’t curry more.
So we just call the function.
Then we can call it by writing:
const add = (x, y, z) => x + y + z;
const sum = curry(add)(1)(2)(3);
We curried the function, so we call the curried function with their individual arguments.
And sum
is 6 since we add all the numbers together.
Conclusion
We can curry functions so that we can create functions with some arguments applied and reuse that function for something else.